package com.coocaa.typhoon.api.config.elasticsearch;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * @author bijiahao
 * @date : 2025/10/21 15:40
 * @description
 */
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticsearchProperties {

    /**
     * 集群节点配置
     */
    private Cluster cluster = new Cluster();

    /**
     * 协议 scheme
     */
    private String scheme = "http";

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 连接配置
     */
    private Connection connection = new Connection();

    /**
     * 重试配置
     */
    private Retry retry = new Retry();

    /**
     * 连接池配置
     */
    private Pool pool = new Pool();

    /**
     * 集群发现配置
     */
    private Discovery discovery = new Discovery();

    /**
     * 索引配置
     */
    private Index index = new Index();

    /**
     * 集群节点配置内部类
     */
    @Data
    public static class Cluster {
        /**
         * 节点列表
         */
        private List<Node> nodes = new ArrayList<>();
    }

    /**
     * 节点配置内部类
     */
    @Data
    public static class Node {
        /**
         * 主机地址
         */
        private String host;

        /**
         * 端口号
         */
        private int port = 9200;
    }

    /**
     * 连接配置内部类
     */
    @Data
    public static class Connection {
        /**
         * 连接超时时间
         */
        private String timeout = "10s";

        /**
         * Socket超时时间
         */
        private String socketTimeout = "30s";

        /**
         * 请求超时时间
         */
        private String requestTimeout = "30s";
    }

    /**
     * 重试配置内部类
     */
    @Data
    public static class Retry {
        /**
         * 最大重试超时时间
         */
        private String maxTimeout = "60s";

        /**
         * 最大重试次数
         */
        private int maxRetries = 3;
    }

    /**
     * 连接池配置内部类
     */
    @Data
    public static class Pool {
        /**
         * 最大连接数
         */
        private int maxTotal = 50;

        /**
         * 每路由最大连接数
         */
        private int defaultMaxPerRoute = 20;

        /**
         * 连接空闲验证时间
         */
        private String validateAfterInactivity = "5s";
    }

    /**
     * 集群发现配置内部类
     */
    @Data
    public static class Discovery {
        /**
         * 是否启用节点发现
         */
        private boolean enabled = true;

        /**
         * 节点嗅探间隔
         */
        private String sniffInterval = "60s";

        /**
         * 节点嗅探延迟
         */
        private String sniffDelay = "5s";
    }

    /**
     * 索引配置内部类
     */
    @Data
    public static class Index {
        /**
         * 是否自动创建索引
         */
        private boolean autoCreate = false;

        /**
         * 分片数量
         */
        private int numberOfShards = 3;

        /**
         * 副本数量
         */
        private int numberOfReplicas = 1;
    }

    /**
     * 获取所有节点的HttpHost数组
     *
     * @return HttpHost数组
     */
    public HttpHost[] getHttpHosts() {
        if (cluster == null || cluster.getNodes() == null || cluster.getNodes().isEmpty()) {
            // 如果没有配置节点，返回默认节点
            log.info("nacos没有配置节点，使用默认节点172.16.66.37");
            return new HttpHost[]{
                    new HttpHost("172.16.66.37", 9200, scheme)
            };
        }

        List<HttpHost> hostList = new ArrayList<>();
        for (Node node : cluster.getNodes()) {
            hostList.add(new HttpHost(node.getHost(), node.getPort(), scheme));
        }
        return hostList.toArray(new HttpHost[0]);
    }

    /**
     * 获取节点信息字符串（用于日志输出）
     *
     * @return 节点信息字符串
     */
    public String getNodesInfo() {
        if (cluster == null || cluster.getNodes() == null || cluster.getNodes().isEmpty()) {
            return "未配置节点";
        }

        StringBuilder sb = new StringBuilder();
        for (Node node : cluster.getNodes()) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(node.getHost()).append(":").append(node.getPort());
        }
        return sb.toString();
    }

    /**
     * 检查是否配置了认证信息
     *
     * @return 是否配置了认证
     */
    public boolean hasAuth() {
        return username != null && !username.trim().isEmpty() &&
                password != null && !password.trim().isEmpty();
    }

    /**
     * 获取连接超时时间（毫秒）
     *
     * @return 连接超时毫秒数
     */
    public int getConnectionTimeoutMillis() {
        return parseDurationToMillis(connection.getTimeout());
    }

    /**
     * 获取Socket超时时间（毫秒）
     *
     * @return Socket超时毫秒数
     */
    public int getSocketTimeoutMillis() {
        return parseDurationToMillis(connection.getSocketTimeout());
    }

    /**
     * 获取请求超时时间（毫秒）
     *
     * @return 请求超时毫秒数
     */
    public int getRequestTimeoutMillis() {
        return parseDurationToMillis(connection.getRequestTimeout());
    }

    /**
     * 将持续时间字符串转换为毫秒
     *
     * @param duration 持续时间字符串，如 "10s", "30s"
     * @return 毫秒数
     */
    public int parseDurationToMillis(String duration) {
        if (duration == null || duration.trim().isEmpty()) {
            return 30000; // 默认30秒
        }

        try {
            duration = duration.trim().toLowerCase();
            if (duration.endsWith("ms")) {
                return Integer.parseInt(duration.substring(0, duration.length() - 2));
            } else if (duration.endsWith("s")) {
                return Integer.parseInt(duration.substring(0, duration.length() - 1)) * 1000;
            } else if (duration.endsWith("m")) {
                return Integer.parseInt(duration.substring(0, duration.length() - 1)) * 60 * 1000;
            } else {
                return Integer.parseInt(duration) * 1000; // 默认按秒处理
            }
        } catch (NumberFormatException e) {
            return 30000; // 解析失败返回默认30秒
        }
    }
}
